package dreher;

import processing.core.*; 
 

import controlP5.*; 
import circus.*; 



public class Dreher extends PApplet {

	private static String MOTHER = "m";
	private static String CHILD = "c";
	
	/** 
	 * CONFIG
	 */
	private static String MODE = "projection";
	static int BEAMER = 1; 
	static String TYPE = MOTHER;


	private float rotVal = 0f;
	public OscCloud cloud;

////////// Setting for BEAMER 1

float[][] points00 = {{0,0},{400,0},{400,560},{0,560}};
float[][] spacePoints00 = {{0,400,0}, {400,400,0} , {400,0,-400} , {0,0,-400}};

float[][] points01 = {{560,280},{280,560},{400,680},{0,680},{0,280},{280,0}}; //starts at three o'clock
float[][] spacePoints01 = {{560,800,0},{280,520,0},{400,400,0},{0,400,0},{0,800,0},{280,1080,0}}; 

float[][] points02 = {{280,0},{560,280},{280,560},{0,280}}; 
float[][] spacePoints02 = {{280,1270,531.2f},{560,1175,265.6f},{280,1080,0},{0,1175,265.6f}}; /// this should be correct???
////float[][] spacePoints02 = {{280,1080,0},{560,1175,265.6},{280,1270,531.2f},{0,1175,265.6}};

////////// Setting for BEAMER 2

float[][] points10 = {{400,0},{800,0},{800,400},{0,400}};
float[][] spacePoints10 = {{400,400,0},{400,400,400},{400,0,400},{400,0,-400}};

float[][] points11 = {{0,0},{400,0},{400,160},{0,160}};
float[][] spacePoints11 = {{280,520,0},{280,520,400},{400,400,400},{400,400,0}};

float[][] points12 = {{0,0},{400,0},{400,400},{0,400}};
float[][] spacePoints12 ={{560,800,0},{560,800,400},{280,520,400},{280,520,0}};

float[][] points13 = {{0,0},{400,400},{0,400}};
float[][] spacePoints13 = {{560,800,0},{280,1080,0},{560,800,400}};

float[][] points14 = {{0,0},{400,0},{400,400}};
float[][] spacePoints14 = {{280,1080,0},{560,1175,265.6f},{560,800,400}};

float[][] points15 = {{0,0},{400,0},{400,400},{0,400}};
float[][] spacePoints15 = {{280,1270,531.2f},{280,890,665.6f},{560,800,400},{560,1175,265.6f}};

////////// Setting for BEAMER 3

float[][] points20 = {{400,400},{800,800},{400,800},{0,400},{0,0},{400,0}};
float[][] spacePoints20 = {{0,400,0},{0,0,-400},{0,0,0},{0,400,400},{0,800,400},{0,800,0}};

float[][] points21 = {{0,400},{400,0},{400,400}};
float[][] spacePoints21 = {{0,800,400},{280,1080,0},{0,800,0}};

float[][] points22 = {{0,400},{0,0},{400,0}};
float[][] spacePoints22 = {{0,800,400},{0,1175,265.6f},{280,1080,0}};

float[][] points23 = {{0,0},{400,0},{400,400},{0,400}};
float[][] spacePoints23 = {{280,1270,531.2f},{0,1175,265.6f},{0,800,400},{280,890,665.6f}};

////////// Setting for BEAMER 4

float[][] points30 = {{0,0},{560,0},{280,480}};
float[][] spacePoints30 = {{400,0,400},{0,400,400},{0,0,0}};

float[][] points31 = {{0,0},{560,0},{560,400},{160,800},{160,400},{280,280}};
float[][] spacePoints31 = {{560,800,400},{0,800,400},{0,400,400},{400,0,400},{400,400,400},{280,520,400}};

float[][] points32 = {{280,0},{560,280},{0,280}};
float[][] spacePoints32 = {{280,890,665.6f},{0,800,400},{560,800,400}};

float xMin = 0.0f;
float xMax = 560.0f;
float yMin = 0.0f;
float yMax = 1270.0f;
float zMin = -400.0f;
float zMax = 665.6f;
float xSpan = xMax -xMin;
float ySpan = yMax -yMin;
float zSpan = zMax -zMin;

float myAlpha = 191;

float offSet = 100;
int xCount = (int)(2*xSpan/offSet) +1 ;
int yCount = (int)(2*ySpan/offSet) +1;
int zCount = (int)(2*zSpan/offSet) +1;
GridLine[] grlX = new GridLine[xCount];
GridLine[] grlY = new GridLine[yCount];
GridLine[] grlZ = new GridLine[zCount];

float tX = xMin;
float tY = yMin;
float tZ = zMin;

float tInc = 0;


int shapeID = 0;
boolean firstFrame = true;
int currentShapeID = 0;

ProjectionMapper mapper;

public void setup() {
  size(1280, 960, P3D); //JAVA2D for settings, P3D for sketch & projection
  mapper = new ProjectionMapper(this, MODE, BEAMER, shapeID); //settings, sketch, projection /// "setup-nr.", "shape-nr."
  for (int i = 0; i < xCount; i++) {
   ////////////// the constructor of the GridLine object needs a value for the offset of the plane, as well as its normal vector ('x','y' or 'z' are accepted)
    grlX[i] = new GridLine (this,tX+i*offSet, 'x');
  }
  for (int i = 0; i < yCount; i++) {
  grlY[i] = new GridLine (this,tY+i*offSet, 'y');
  }
  for (int i = 0; i < zCount; i++) {
  grlZ[i] = new GridLine (this,tZ+i*offSet, 'z');
  }
  frameRate(30);
  strokeCap(ROUND);
  if(TYPE==MOTHER){
		//cloud = new OscCloudEx(this, "parent", "10.254.255.205", 1337);
		cloud = new OscCloud(this, "parent", "192.168.0.1", 13370);
		//cloud.running = true;
	}else if(TYPE==CHILD){
	  //cloud = new OscCloudEx(this, "child", "10.254.255.205", 1338, "10.254.255.205", 1337);
		cloud = new OscCloud(this, "child", "192.168.0.3", 13380, "192.168.0.1", 13370);
	}
}

public void draw() {
  if(mapper.ready && !mapper.config) {
    background(0);

    for (int j = 0; j < mapper.textures.length; j++) {
     int[][] points = mapper.shapePoints(j);
     
    beginShape();
   noStroke();
     fill(255*j/(float)mapper.textures.length,0,127,127);
    for(int k=0; k<points.length; k++) {
      vertex(points[k][0], points[k][1]);
    }
     endShape(CLOSE);
    
    noFill();
   stroke(255);
  strokeWeight(6);


  //////////////////// to move the Plane in space (along its normal vector), use either the incPlane() or the resetPlane() function. in the first case, the argument is added, in the second, reset.
  for (int i = 0; i < xCount; i++) {
  grlX[i].resetPlane((grlX[i].planeValue+tInc-xMin)%(float)((xCount-1)*offSet)+xMin);
  }
  for (int i = 0; i < yCount; i++) {
  grlY[i].resetPlane((grlY[i].planeValue+tInc-yMin)%(float)((yCount-1)*offSet)+yMin);
  }
  for (int i = 0; i < zCount; i++) {
  grlZ[i].resetPlane((grlZ[i].planeValue+tInc-zMin)%(float)((zCount-1)*offSet)+zMin);
  }
  
      for (int i = 0; i < zCount; i++) {
    //grlZ[i].trans(xSpan/2f,ySpan/2f,zSpan/2f);
    	  if(TYPE==MOTHER){
    		  rotVal = (TWO_PI/360f*0.02f);
    		  //System.out.println(String.valueOf(rotVal));
    		  cloud.send("rVal", String.valueOf(rotVal));
    		  //cloud.send("/rotVal", "holzhammer");
    	  }
    grlZ[i].rotY(rotVal);

   // grlZ[i].trans(-xSpan/2f,-ySpan/2f,-zSpan/2f);
}

   /////////////// for a representation in a texture shape, use the below function, ist argument are the projection settings (e.g. BEAMER_1) and the current shape it is being drawn into. 
     for (int i = 0; i < xCount; i++) {
  //grlX[i].drawLineInPlane(settingsID,j);
     }
     for (int i = 0; i < yCount; i++) {
 // grlY[i].drawLineInPlane(settingsID,j);
     }
     for (int i = 0; i < zCount; i++) {
       //strokeWeight(i*100/(float)zCount);
  grlZ[i].drawLineInPlane(BEAMER,j);
  }
  ///  fill(255,127);
   //// ellipse(map(mouseX,0,width,mapper.shapeMinX(j),mapper.shapeMaxX(j)),map(mouseY,0,height,mapper.shapeMinY(j),mapper.shapeMaxY(j)),20,20);
    mapper.textures[j] = get();
    background(0);
    }
  }

}

public void controlEvent(ControlEvent theEvent) {
  mapper.controlEvent(theEvent);
}

public void incomingMessage(String message, String content){
	System.out.println("theContent: "+content);
	  if(TYPE==CHILD){
		  rotVal = Float.valueOf(content.trim()).floatValue();
	  }
}



public void mousePressed () {
}

public void mouseDragged () {
}



public void drawEverything () {
  int points[][];
  for (int i = 0; i < mapper.textures.length; i++) {
    points = mapper.shapePoints(i);
    beginShape();
    fill(255*i/(float)mapper.textures.length,0,127,127);
    for(int j=0; j<points.length; j++) {
      vertex(points[j][0], points[j][1]);
    }
    endShape(CLOSE);
    fill(255,127);
    ellipse(map(mouseX,0,width,mapper.shapeMinX(0),mapper.shapeMaxX(0)),map(mouseY,0,height,mapper.shapeMinY(0),mapper.shapeMaxY(0)),10,10);


    mapper.textures[i] = get();
    background(0);
  }
}

public void printPoints (int theShapeID) {
  println();
  int points[][];
  points = mapper.shapePoints(theShapeID);
  for (int j=0; j<points.length; j++) {
    println("point #" + j + " : x= "+points[j][0] +" : y= " +points[j][1]);
  }
}



public void printArray (int theShapeID) {

  int points[][];
  print("{");
  points = mapper.shapePoints(theShapeID);
  for (int j=0; j<points.length; j++) {
    print("{"+points[j][0] +"," +points[j][1]+"}");
    if (j != points.length-1) print(",");
  }
  print("};");
  println();
}

public void printStats(int theShapeID) {
  println(); 
  println("shape Nr. " + theShapeID);
  println("min x: " + mapper.shapeMinX(theShapeID));
  println("min y: " + mapper.shapeMinY(theShapeID));
  println("max x: " + mapper.shapeMaxX(theShapeID));
  println("max y: " + mapper.shapeMaxY(theShapeID));
  println("height: " + mapper.shapeHeight(theShapeID));
  println("width: " + mapper.shapeWidth(theShapeID));
}

  static public void main(String args[]) {
	  //PApplet.main(new String[] { "--present", dreher.Dreher.class.getName()}); 
	  PApplet.main(new String[] { "--bgcolor=#F0F0F0", dreher.Dreher.class.getName() });
  }
}
